(function (line, browser, document, global) {
    var rMouseEvent = /^(?:mouse|contextmenu)|click/,
        rKeyboardEvent = /^(?:key(?:down|press|up))$/,
        rMousewheel = /^(?:DOMMouseScroll|mousewheel)$/;
    line.define('line.event.EventFactory', null, {
        methods:{
            init:function (original) {
                this.originalEvent = original;
            },
            wrap:function () {
                var evt = this.originalEvent,
                    type = evt.type;
                if (rMouseEvent.test(type)) {
                    return new line.event.MouseEvent(evt);
                } else if (rKeyboardEvent.test(type)) {
                    return new line.event.KeyBoardEvent(evt);
                } else if (rMousewheel.test(type)) {
                    return new line.event.Mousewheel(evt);
                } else {
                    return new line.event.Event(evt);
                }
            }
        }
    });
    line.define('line.event.Event', null, {
        methods:{
            init:function (original) {
                this.originalEvent = original;
                this.type = original.type;
            },
            getEventDoc:function () {
                return line.getDoc(this.getTarget());
            },
            getEventRoot:function () {
                var eventDoc = this.getEventDoc();
                return  (browser.isStrict) ? eventDoc.documentElement : eventDoc.body;
            },
            getEvent:function () {
                var window = line.getWindow();
                return this.originalEvent || window.event;
            },
            getTarget:function () {
                var evt = this.originalEvent;
                return evt.target || evt.srcElement;
            },
            getMetaKey:function () {
                return !!this.originalEvent.metaKey;
            },
            preventDefault:function () {
                var evt = this.originalEvent;
                if (evt.preventDefault) {
                    evt.preventDefault();
                } else {
                    evt.returnValue = false;
                }
            },
            stopPropagation:function () {
                var evt = this.originalEvent;
                if (evt.stopPropagation) {
                    evt.stopPropagation();
                } else {
                    evt.cancelBubble = true;
                }
            }
        }
    });
    line.define('line.event.MouseEvent', line.event.Event, {
        methods:{
            getPageX:function () {
                var root = this.getEventRoot(),
                    evt = this.originalEvent;
                return evt.clientX + ( root.scrollLeft || 0 ) - ( root.clientLeft || 0 );
            },
            getPageY:function () {
                var root = this.getEventRoot(),
                    evt = this.originalEvent;
                return evt.clientY + ( root.scrollTop || 0 ) - ( root.clientTop || 0 );
            },
            getOffsetX:function () {
                var target = this.getTarget(),
                    offsetLeft = line.dom.offset(target).left;
                return this.getPageX() - offsetLeft;
            },
            getOffsetY:function () {
                var target = this.getTarget(),
                    offsetTop = line.dom.offset(target).top;
                return this.getPageY() - offsetTop;
            },
            /*
             // 为 click 事件添加 which 属性，左1 中2 右3
             // IE button的含义：
             // 0：没有键被按下
             // 1：按下左键
             // 2：按下右键
             // 3：左键与右键同时被按下
             // 4：按下中键
             // 5：左键与中键同时被按下
             // 6：中键与右键同时被按下
             // 7：三个键同时被按下
             */
            getWhich:function () {
                var button = this.originalEvent.button;
                return [ 0, 1, 3, 0, 2, 0, 0, 0 ]
                button;
            }
        }
    });
    line.define('line.event.KeyBoardEvent', line.event.Event, {
        methods:{
            getKeyCode:function () {
                var evt = this.originalEvent;
                return evt.charCode || evt.keyCode;
            }
        }
    });
    line.define('line.event.Mousewheel', line.event.Event, {
        methods:{
            getWheelDelta:function () {
                var evt = this.originalEvent;
                if ('wheelDelta' in evt) {
                    return Math.round(evt.wheelDelta);
                } else if ('detail' in evt) {
                    return -evt.detail * 40;
                }
            }
        }
    });
}(line, line.browser, document, window));